package com.tianji.learning.redis;

import cn.hutool.core.util.StrUtil;
import com.tianji.learning.delay.DelayTask;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.DelayQueue;

@Slf4j
@Component
@RequiredArgsConstructor
public class RedisOfLearningRecord {
    private String KEY_TEMPLATE = "learning:record:{}";
    private final RedisTemplate redisTemplate;
    private DelayQueue<DelayTask<LearningRecordFormDTO>> delayTasksQueue = new DelayQueue<>();
    private final ILearningLessonService learningLessonService;
    private final LearningRecordMapper learningRecordMapper;
    private static boolean flag = true;


    @PostConstruct
    public void init(){
//        new Thread(()->handleDelayTask());
        CompletableFuture.runAsync(()->handleDelayTask());

    }

    @PreDestroy
    public void destroy(){
        log.info("关闭延时任务线程池");
        flag = false;
    }

    /**
     * 处理延时检测任务
     */
    private void handleDelayTask() {
        log.info("开始处理播放进度延时监测任务逻辑");
        while (flag) {
            try {
                // 2.获取任务
                DelayTask<LearningRecordFormDTO> task = delayTasksQueue.take();
                // 3.获取任务中的数据
                LearningRecordFormDTO data = task.getData();
                // 4.执行任务
                log.info("执行任务：{}", data);
                // 从redis中查询数据
                LearningRecord record = readLearningRecordFromCache(data.getLessonId(), data.getSectionId());
                // 比较播放进度是否一致
                if (record.getMoment() != data.getMoment()){
                    continue;
                }else {
                    log.info("用户停止播放，更新数据库");
                    // 更新学习记录
                    record.setMoment(data.getMoment());
                    learningRecordMapper.updateById(record);
                    // 更新课表
                    learningLessonService.lambdaUpdate()
                            .eq(LearningLesson::getId, data.getLessonId())
                            .set(LearningLesson::getLatestSectionId, data.getSectionId())
                            .set(LearningLesson::getLatestLearnTime, data.getCommitTime())
                            .update();
                }
            } catch (InterruptedException e) {
                log.info("获取任务失败");
            }
        }
    }


    /**
     * 从redis查询学习记录
     */
    public LearningRecord readLearningRecordFromCache(Long lessonId, Long sectionId) {
        log.info("从缓存中查询学习记录，课程表ID{}，小节ID：{}",lessonId, sectionId);

        // 1.组装大key
        String key = StrUtil.format(KEY_TEMPLATE, lessonId);

        // 2.小key
        String hashKey = sectionId.toString();

        // 3.发起查询
        LearningRecord record = (LearningRecord)redisTemplate.opsForHash().get(key, hashKey);
        return record;
    }

    /**
     * 将学习记录存入redis中
     */
    public void saveLearningRecordToCache(LearningRecord record) {
        log.info("将学习记录存入redis中，课程表ID{}，小节ID：{}",record.getLessonId(), record.getSectionId());

        // 1.组装大key
        String key = StrUtil.format(KEY_TEMPLATE, record.getLessonId());

        // 2.小key
        String hashKey = record.getSectionId().toString();

        // 3.发起查询
        redisTemplate.opsForHash().put(key, hashKey, record);
        redisTemplate.expire(key, Duration.ofMinutes(1));
    }

    /**
     * 将提交记录更新到redis中
     */
    public void updateLearningRecordToCache(LearningRecordFormDTO dto) {
        log.info("将提交记录更新到redis中，课程表ID{}，小节ID：{}",dto.getLessonId(), dto.getSectionId());

        // 1.组装大key
        String key = StrUtil.format(KEY_TEMPLATE, dto.getLessonId());

        // 2.小key
        String hashKey = dto.getSectionId().toString();

        // 3.组装hashvalue
        LearningRecord record = (LearningRecord) redisTemplate.opsForHash().get(key, hashKey);
        record.setMoment(dto.getMoment());

        // 4.存入数据
        redisTemplate.opsForHash().put(key, hashKey, record);
        redisTemplate.expire(key, Duration.ofMinutes(1));
    }

    /**
     * 删除redis中的学习记录
     */
    public void deleteLearningRecordFromCache(Long lessonId, Long sectionId) {
        log.info("从缓存中删除学习记录，课程表ID{}，小节ID：{}",lessonId, sectionId);

        // 1.组装大key
        String key = StrUtil.format(KEY_TEMPLATE, lessonId);

        // 2.小key
        String hashKey = sectionId.toString();

        // 3.发起删除
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    /**
     * 缓存数据，并提交延时任务
     */
    public void submitDelayTask(LearningRecordFormDTO learningRecordFormDTO) {
        // 1.缓存数据
        updateLearningRecordToCache(learningRecordFormDTO);

        // 2.提交延时任务
        delayTasksQueue.add(new DelayTask<>(Duration.ofSeconds(20), learningRecordFormDTO));
    }

}
